package com.glsc.ngateway.opmanage.service.deposit;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.glsc.ngateway.common.api.common.enums.Constant;
import com.glsc.ngateway.common.api.common.utils.PageUtil;
import com.glsc.ngateway.common.api.oaflow.dto.XinYiParamDto;
import com.glsc.ngateway.common.base.domain.mysql.gateway.platform.User;
import com.glsc.ngateway.common.base.domain.mysql.opmanagemain.deposit.DepositoryBank;
import com.glsc.ngateway.common.base.domain.mysql.opmanagemain.deposit.DepositoryDayEndTrial;
import com.glsc.ngateway.common.base.domain.mysql.opmanagemain.deposit.DepositoryPaymentPlan;
import com.glsc.ngateway.common.base.domain.mysql.opmanagemain.deposit.DepositoryPaymentPlanXinYiLog;
import com.glsc.ngateway.common.base.domain.mysql.opmanagemain.xinyi.XinYiDefineLog;
import com.glsc.ngateway.common.base.domain.mysql.opmanagemain.xinyi.XinYiDefineTemplate;
import com.glsc.ngateway.common.base.domain.mysql.opmanagemain.xinyi.XinYiDefineTemplateItem;
import com.glsc.ngateway.common.base.repo.mysql.opmanagemain.deposit.DepositoryPaymentPlanRepository;
import com.glsc.ngateway.opmanage.service.SystemConfigService;
import com.glsc.ngateway.opmanage.service.feign.GatewayFeignService;
import com.glsc.ngateway.opmanage.utils.DateUtils;
import com.glsc.ngateway.opmanage.utils.SpecificationUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.compress.utils.Lists;
import org.apache.commons.lang.StringUtils;
import org.springframework.data.domain.*;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import javax.annotation.Resource;
import javax.transaction.Transactional;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

@Service
@Slf4j
public class DepositoryPaymentPlanService {
    private static final Integer GATEWAY_RET_CODE_SUCCESS = 0;

    @Resource
    private DepositoryPaymentPlanRepository depositoryPaymentPlanRepository;

    @Resource
    private DepositoryDayEndTrialService depositoryDayEndTrialService;

    @Resource
    private DepositoryBankService depositoryBankService;

    @Resource
    private SystemConfigService systemConfigService;

    @Resource
    private GatewayFeignService gatewayFeignService;

    @Resource
    private DepositoryPaymentPlanXinYiLogService depositoryPaymentPlanXinYiLogService;


    /**
     * 分页查询资金划拨方案
     *
     * @param pageNo
     * @param pageSize
     * @param param
     * @return
     */
    public Page<DepositoryPaymentPlan> page(int pageNo, int pageSize, Map<String, Object> param) {
        Sort.Direction direction = Sort.Direction.DESC;
        String sort = "createTime";

        if (Objects.isNull(param.get("EQ_effectDate"))) {
            param.put("EQ_effectDate", DateUtils.getNowDateString());
        }

        pageNo = PageUtil.initPageNo(pageNo);
        pageSize = PageUtil.initPageSize(pageSize);

        Pageable pageable = PageRequest.of(pageNo - 1, pageSize, direction, sort);
        Page<DepositoryPaymentPlan> page = depositoryPaymentPlanRepository.findAll(SpecificationUtil.buildSpecification(param, DepositoryPaymentPlan.class), pageable);

        return page;
    }

    /**
     * 查询指定日期的资金划拨计划
     *
     * @param date
     * @return
     */
    public List<DepositoryPaymentPlan> listByDate(String date) {
        List<DepositoryPaymentPlan> list = depositoryPaymentPlanRepository.findAll(Example.of(DepositoryPaymentPlan.builder().deleted("N").effectDate(DateUtils.getNowDateString()).build()));
        return list;
    }


    /**
     * 创建今日资金划拨方案
     */
    @Transactional
    public void create(Long userId, String userName) {
        List<DepositoryDayEndTrial> endTrials = depositoryDayEndTrialService.listByDate(DateUtils.getNowDateString());
        Assert.isTrue(CollectionUtils.isNotEmpty(endTrials), "请先试算[保证金-日终]数据");

        //检查是否需要删除今日历史数据
        List<DepositoryPaymentPlan> oldPlans = listByDate(DateUtils.getNowDateString());
        if (CollectionUtils.isNotEmpty(oldPlans)) {
            deleteAllByIds(oldPlans.stream().map(DepositoryPaymentPlan::getId).collect(Collectors.toList()));
        }

        List<DepositoryPaymentPlan> plans = Lists.newArrayList();

        List<DepositoryBank> banks = depositoryBankService.listAll();
        Map<String, DepositoryBank> bankMap = banks.stream().collect(Collectors.toMap(DepositoryBank::getBankName, e -> e, (i, j) -> j));
        for (DepositoryDayEndTrial endTrial : endTrials) {
            DepositoryPaymentPlan plan = DepositoryPaymentPlan.builder().deleted("N").build();

            if (Objects.isNull(endTrial.getAdjustValue())) {
                continue;
            }

            DepositoryBank depositoryBank = bankMap.get(endTrial.getBankName());
            if (Objects.isNull(depositoryBank)) {
                continue;
            }

            /*if (StringUtils.isEmpty(depositoryBank.getAccount()) || StringUtils.isEmpty(depositoryBank.getAccountName()) || StringUtils.isEmpty(depositoryBank.getOpenAccountBank())) {
                continue;
            }*/

            int compareValue = endTrial.getAdjustValue().compareTo(BigDecimal.ZERO);
            if (compareValue == 0) {
                continue;
            } else if (compareValue > 0) {
                plan.setName("建行3568 -> " + endTrial.getBankName());

                plan.setPayBankAcc("32001618636050003568");
                plan.setPayBankAccName("国联证券股份有限公司（客户）");
                plan.setPayOpenAccountBank("中国建设银行股份有限公司无锡分行营业部");

                plan.setRecBankAcc(depositoryBank.getAccount());
                plan.setRecBankAccName(depositoryBank.getAccountName());
                plan.setRecOpenAccountBank(depositoryBank.getOpenAccountBank());

            } else if (compareValue < 0) {
                plan.setName(endTrial.getBankName() + " -> 建行3568");

                plan.setRecBankAcc("32001618636050003568");
                plan.setRecBankAccName("国联证券股份有限公司（客户）");
                plan.setRecOpenAccountBank("中国建设银行股份有限公司无锡分行营业部");

                plan.setPayBankAcc(depositoryBank.getAccount());
                plan.setPayBankAccName(depositoryBank.getAccountName());
                plan.setPayOpenAccountBank(depositoryBank.getOpenAccountBank());
            }

            plan.setEffectDate(DateUtils.getNowDateString());


            plan.setOccurAmt(endTrial.getAdjustValue().setScale(2, RoundingMode.HALF_UP).abs().toString());

            plan.setMemo("保证金日终划拨[" + plan.getName() + "]");

            plan.setCreateId(userId);
            plan.setCreateName(userName);
            plans.add(plan);
        }

        if (CollectionUtils.isNotEmpty(plans)) {
            depositoryPaymentPlanRepository.saveAll(plans);
        }

    }

    /**
     * 保存
     *
     * @param plan
     * @return
     */
    public DepositoryPaymentPlan save(DepositoryPaymentPlan plan) {
        if (Objects.isNull(plan)) {
            return null;
        }
        return depositoryPaymentPlanRepository.save(plan);
    }

    /**
     * 根据id批量删除
     *
     * @param ids
     */
    public void deleteAllByIds(List<Integer> ids) {
        depositoryPaymentPlanRepository.deleteAllById(ids);
    }

    /**
     * 根据id删除
     *
     * @param id
     */
    public void deleteAllById(Integer id) {
        depositoryPaymentPlanRepository.deleteById(id);
    }

    /**
     * 发送新意指令并记录日志
     *
     * @param user
     */
    public void send(User user, List<Integer> ids) {
        if (CollectionUtils.isEmpty(ids)) {
            return;
        }

        List<DepositoryPaymentPlan> plans = listByDate(DateUtils.getNowDateString());
        if (CollectionUtil.isEmpty(plans)) {
            return;
        }

        plans = plans.stream().filter(e -> ids.contains(e.getId())).collect(Collectors.toList());
        if (CollectionUtil.isEmpty(plans)) {
            return;
        }

        String date = DateUtils.reFormatDate(DateUtils.getNowDateString(), DateUtils.formatDate_, DateUtils.formatDate);

        for (DepositoryPaymentPlan plan : plans) {
            DepositoryPaymentPlanXinYiLog yiDefineLog = DepositoryPaymentPlanXinYiLog.builder().effectDate(DateUtils.getNowDateString()).name(plan.getName()).planId(plan.getId()).deleted("N").type("日终").build();
            try {
                String paramJson = systemConfigService.findConfigValueByCode(Constant.CONFIG_KEY_SYNC_OA_FORM_DATA_XIN_YI_FIELD);
                XinYiParamDto paramDto = JSONObject.parseObject(paramJson, XinYiParamDto.class);
                paramDto.setOutInstId("glsc-" + System.currentTimeMillis());

                paramDto.buildRecInfo(plan.getRecBankAccName(), plan.getRecBankAcc(), plan.getRecOpenAccountBank(), "9999").buildPayInfo(plan.getPayBankAccName(), plan.getPayBankAcc(), plan.getPayOpenAccountBank(), "9999").buildDateInfo(date, date, date).setOccurAmt(plan.getOccurAmt()).setNote(plan.getMemo()).setPayBigBankAcc(plan.getPayBigBankAcc()).setRecBigBankAcc(plan.getRecBigBankAcc());

                if (StringUtils.isEmpty(paramDto.getNote())) {
                    paramDto.setNote("默认划款摘要");
                }

                String ret = gatewayFeignService.callXy(JSON.toJSONString(paramDto));
                log.info("保证金日中划拨触发新意{}", ret);

                JSONObject retObject = JSONObject.parseObject(ret);

                yiDefineLog = DepositoryPaymentPlanXinYiLog.builder().name(plan.getName()).planId(plan.getId()).occurAmt(plan.getOccurAmt()).deleted("N").effectDate(DateUtils.getNowDateString()).recBankAcc(plan.getRecBankAcc()).recBankAccName(plan.getRecBankAccName()).recOpenAccountBank(plan.getRecOpenAccountBank()).recBigBankAcc(plan.getRecBigBankAcc()).payBankAcc(plan.getPayBankAcc()).payBankAccName(plan.getPayBankAccName()).payOpenAccountBank(plan.getPayOpenAccountBank()).payBigBankAcc(plan.getPayBigBankAcc()).type("日终").build();
                yiDefineLog.setStatus("Y");

                if (StrUtil.isEmpty(ret) || null == retObject || null == retObject.get("code") || !GATEWAY_RET_CODE_SUCCESS.equals(retObject.get("code")) || Objects.isNull(retObject.getJSONObject("msg")) || !"0".equals(retObject.getJSONObject("msg").getString("retCode"))) {
                    yiDefineLog.setStatus("N");
                }

                yiDefineLog.setCreateId(user.getId());
                yiDefineLog.setCreateName(user.getName());
                depositoryPaymentPlanXinYiLogService.save(yiDefineLog);
            } catch (Exception e) {
                yiDefineLog.setStatus("N");
                depositoryPaymentPlanXinYiLogService.save(yiDefineLog);
                log.error("自定以新意指令创建失败:", e);
            }
        }
    }


}